package jp.sourceforge.talisman.mds.distance;

/*
 * $Id: MinkowskyItemDistanceCalculator.java,v 1.1 2009/09/12 05:06:09 weiwei Exp $
 */

/**
 * Minkowsky distance calculator.
 *
 * When p-value is 1, then this calculator is same {@link
 * CityBlockItemDistanceCalculator
 * <code>CityBlockDistanceCalculator</code>}.
 * When p-value is 2, then this calculator is same {@link
 * EuclideanItemDistanceCalculator
 * <code>EuclideanDistanceCalculator</code>}.
 * <pre>
 * D(x, y) = \sqrt[p]{\sigma^r_{k=1} (x_k - y_k)^p}
 * </pre>
 * 
 * @author Haruaki Tamada
 * @version $Revision: 1.1 $ 
 */
public class MinkowskyItemDistanceCalculator extends AbstractItemDistanceCalculator{
    private int pvalue;

    /**
     * setPValue(3);
     */
    public MinkowskyItemDistanceCalculator(){
        this(3);
    }

    public MinkowskyItemDistanceCalculator(int pvalue){
        setPValue(pvalue);
    }

    public double getPValue(){
        return pvalue;
    }

    public void setPValue(int pvalue){
        this.pvalue = pvalue;
    }

    @Override
    public ItemDistanceAlgorithm getAlgorithm(){
        return ItemDistanceAlgorithm.MINKOWSKY_DISTANCE;
    }

    @Override
    public synchronized double calculate(double[] x, double[] y){
        validateArguments(x, y);

        double value = 0d;
        for(int i = 0; i < x.length; i++){
            if(!Double.isNaN(x[i]) && !Double.isNaN(y[i])){
                double diff = Math.abs(x[i] - y[i]);
                value += Math.pow(diff, getPValue());
            }
        }
        return Math.pow(value, 1 / getPValue());
    }
}
